package com.tools.cleanmaster.scenenew;

import android.annotation.SuppressLint;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.BatteryManager;
import android.os.Build;

import com.tools.cleanmaster.CleanApplication;
import com.tools.cleanmaster.store.GlobalConfigSharedPrefManager;
import com.tools.cleanmaster.utils.FeatureConfig;
import com.tools.cleanmaster.utils.LogHelper;

import java.util.LinkedList;
import java.util.List;


public class BatteryInfoTracker {
    private static final String TAG = "BatteryInfoTracker";
    private static final boolean DEBUG = FeatureConfig.DEBUG_LOG;

    @SuppressLint("InlinedApi")
    private static final int BATTERY_PLUGGED_ANY = BatteryManager.BATTERY_PLUGGED_AC
            | BatteryManager.BATTERY_PLUGGED_USB
            | (Build.VERSION.SDK_INT >= 17 ? BatteryManager.BATTERY_PLUGGED_WIRELESS : 0);

    private static BatteryInfoTracker sInstance = null;

    public static class BatteryInfo {
        public int level;
        public int scale;
        private int reportedPercent;  // percent reported from driver
        public int percent;  // percent corrected by us
        public int plugType;
        public int status;  // 电量状态
    }

    public interface BatteryInfoListener {
        /**
         * @param newData Read-only, cannot be modified.
         */
        void onBatteryInfoUpdated(BatteryInfo newData);
    }

    private Context mContext;
    private List<BatteryInfoListener> mListeners = new LinkedList<BatteryInfoListener>();
    private BatteryInfo mBatteryInfo;
    private int mBatteryScale = 100;

    private BroadcastReceiver mBatteryInfoReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) {
                processBroadcast(intent);
            }
            //传递给
            CleanApplication.getInstance().getChargingManager().updateChargingState(intent);

        }
    };

    public static synchronized BatteryInfoTracker getInsance(Context cxt) {
        if (sInstance == null) {
            sInstance = new BatteryInfoTracker(cxt);
        }
        return sInstance;
    }

    private BatteryInfoTracker(Context cxt) {
        mContext = cxt.getApplicationContext();
        mBatteryScale = GlobalConfigSharedPrefManager.getBatteryScale(mContext);
    }

    private void start() {
        // Note: only one sticky intent allowed to be added in the following
        // receiver. That's Intent.ACTION_BATTERY_CHANGED!
        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_BATTERY_CHANGED); // sticky intent!
        filter.addAction(Intent.ACTION_BATTERY_LOW);
        filter.addAction(Intent.ACTION_BATTERY_OKAY);
        filter.addAction(Intent.ACTION_POWER_CONNECTED);
        filter.addAction(Intent.ACTION_POWER_DISCONNECTED);
        filter.addAction(Intent.ACTION_SCREEN_OFF);
        filter.addAction(Intent.ACTION_SCREEN_ON);
        filter.addAction(Intent.ACTION_USER_PRESENT);

        Intent lastBatteryUpdateIntent = mContext.registerReceiver(mBatteryInfoReceiver, filter);
        if (lastBatteryUpdateIntent != null) {
            // initialize battery info member data
            updateBatteryInfo(lastBatteryUpdateIntent);
        }
        if (FeatureConfig.DEBUG_LOG) LogHelper.i(TAG, "BatteryInfoTracker, service started");
    }

    private void stop() {
        try {
            mContext.unregisterReceiver(mBatteryInfoReceiver);
            if (FeatureConfig.DEBUG_LOG) LogHelper.i(TAG, "BatteryInfoTracker, service stopped");
        } catch (Exception e) {
            //避免外部多次触发unregisterReceiver
            e.printStackTrace();
        }
    }

    public void registerListener(BatteryInfoListener cb) {

        synchronized (mListeners) {
            if (mListeners.size() == 0) {
                start();
            }
            if (!mListeners.contains(cb)) {
                mListeners.add(cb);
            }
        }

        // Notify the listener to get initialized
        if (mBatteryInfo != null) {
            cb.onBatteryInfoUpdated(mBatteryInfo);
        }
    }

    public void unregisterListener(BatteryInfoListener cb) {
        synchronized (mListeners) {
            mListeners.remove(cb);
            if (mListeners.size() == 0) {
                stop();
            }
        }
    }

    private void notifyListeners(BatteryInfo data) {
        List<BatteryInfoListener> ls = new LinkedList<BatteryInfoListener>();
        synchronized (mListeners) {
            ls.addAll(mListeners);
        }

        // 在listener回调时出现反注册，导致并发修改异常
        // 所以将所有的监听拷贝一份，再做分发
        for (BatteryInfoListener cb : ls) {
            if (cb != null) {
                cb.onBatteryInfoUpdated(data);
            }
        }
    }

    private void processBroadcast(Intent intent) {
        updateBatteryInfo(intent);
    }

    private void updateBatteryInfo(Intent intent) {
        BatteryInfo data = new BatteryInfo();
        data.level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
        data.scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, 100);
        data.plugType = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0);
        data.status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, BatteryManager.BATTERY_STATUS_UNKNOWN);

        fixData(data);

        data.reportedPercent = data.scale < 1 ? data.level : (data.level * 100 / data.scale);
        if (data.reportedPercent >= 0 && data.reportedPercent <= 100)
            data.percent = data.reportedPercent;
        else if (data.reportedPercent < 0) {
            data.percent = 0;
        } else if (data.reportedPercent > 100) {
            data.percent = 100;
        }

        if (DEBUG) LogHelper.d(TAG, "battery info updated, " + dump(data));
        mBatteryInfo = data;

        notifyListeners(data);
    }

    private void fixData(BatteryInfo data) {
        if (Build.DEVICE.equalsIgnoreCase("SCH-i909")) {
            if (Build.VERSION.SDK_INT <= 8 && !Build.VERSION.RELEASE.equals("2.2.2")) {
                data.scale = 1000;
                mBatteryScale = 1000;
                GlobalConfigSharedPrefManager.setBatteryScale(mContext, mBatteryScale);
            }
        }

        // We may need to update 'mBatteryScale'
        if (data.level > data.scale) {
            if (FeatureConfig.DEBUG_LOG) {
                LogHelper.e(TAG, "Bad phone!!! battery level: " + data.level
                        + ", battery scale: " + data.scale
                        + ", mBatteryScale: " + mBatteryScale);
            }
            if (data.level % 100 == 0) {
                mBatteryScale = data.level;
                GlobalConfigSharedPrefManager.setBatteryScale(mContext, mBatteryScale);
            }
        }

        // We may need to correct the 'data.scale'
        if (data.scale < mBatteryScale) {
            data.scale = mBatteryScale;
        }
    }

    public BatteryInfo getBatteryData() {
        return mBatteryInfo;
    }

    public static String dump(BatteryInfo data) {
        return "level:" + data.level + ", scale:" + data.scale
                + ", percent: " + data.percent;
    }

}
